package se.mbaeumer.fxtodo.core.util.dataimport;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import se.mbaeumer.fxtodo.core.main.FXTodoMain;
import se.mbaeumer.fxtodo.core.model.Context;
import se.mbaeumer.fxtodo.core.model.ICSInfo;
import se.mbaeumer.fxtodo.core.model.Task;

public class XMLReader {
	static final String CONTEXTS = "contexts";
	static final String CONTEXT = "context";
	static final String TASKS = "tasks";
	static final String TASK = "task";
	static final String ICS_INFOS = "icsinfos";
	static final String ICS_INFO = "icsinfo";	
	
	private XMLInputFactory xmlInputFactory;
	private XMLEventReader xmlEventReader;
	private FileInputStream fileInputStream;
	private String configFile;
	private List<Context> contexts;
	private List<Task> tasks;
	private List<ICSInfo> icsInfos;
	private FXTodoMain fxtodoMain;

	public XMLReader(FXTodoMain fxtodoMain, String filename)
			throws FileNotFoundException, XMLStreamException {
		this.fxtodoMain = fxtodoMain;
		this.configFile = filename;
		this.init();
	}

	private void init() throws XMLStreamException, FileNotFoundException {
		this.xmlInputFactory = XMLInputFactory.newInstance();
		// Setup a new eventReader
		this.fileInputStream = new FileInputStream(configFile);
		this.xmlEventReader = this.xmlInputFactory
				.createXMLEventReader(this.fileInputStream);
		// Read the XML document
	}

	public void readDataFromFile() throws XMLStreamException {
		while (this.xmlEventReader.hasNext()) {
			XMLEvent event = this.xmlEventReader.nextEvent();

			if (event.isStartElement()) {
				StartElement startElement = event.asStartElement();
				if (startElement.getName().getLocalPart() == (CONTEXTS)) {
					// create the context list
					this.contexts = new ArrayList<Context>();
				}

				if (startElement.getName().getLocalPart() == (CONTEXT)) {
					// create the context
					Context c = new Context.ContextBuilder().build();
					c.setId(new Integer(startElement.getAttributeByName(
							new QName("id")).getValue()));
					c.setTitle(startElement.getAttributeByName(
							new QName("title")).getValue());
					c.setDescription(startElement.getAttributeByName(
							new QName("description")).getValue());

					// TODO: Use constants instead of hard-coded strings
					DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					Date date = new Date();

					try {
						date = df.parse(startElement.getAttributeByName(
								new QName("created")).getValue());
						c.setCreated(date);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					this.contexts.add(c);
				}

				if (startElement.getName().getLocalPart() == (TASKS)) {
					// create the task list
					this.tasks = new ArrayList<Task>();
				}

				if (startElement.getName().getLocalPart() == (TASK)) {
					// create the task
					Task t = new Task.TaskBuilder().build();
					t.setId(new Integer(startElement.getAttributeByName(
							new QName("id")).getValue()));
					t.setTitle(startElement.getAttributeByName(
							new QName("title")).getValue());
					t.setDescription(startElement.getAttributeByName(
							new QName("description")).getValue());
					
					// created
					// TODO: Use constants instead of hard-coded strings
					DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					Date date = new Date();

					try {
						date = df.parse(startElement.getAttributeByName(
								new QName("created")).getValue());
						t.setCreated(date);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					// due date
					// TODO: Use constants instead of hard-coded strings
					df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					date = new Date();

					try {
						date = df.parse(startElement.getAttributeByName(
								new QName("dueDate")).getValue());
						t.setDueDate(date);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					// contextId
					String contextId = startElement.getAttributeByName(
							new QName("contextId")).getValue();
					
					if (contextId == null || contextId.equals("")) {
						
						t.setTaskContext(null);
					} else {
						Context c = new Context.ContextBuilder().
								id(new Integer(contextId).intValue()).build(); 
								
						t.setTaskContext(c);
					}
					// status
					t.setStatus(this.fxtodoMain
							.getStatusByTitle(startElement.getAttributeByName(
									new QName("status")).getValue()));
					// priority
					t.setPriority(this.fxtodoMain
							.getPriorityByTitle(startElement
									.getAttributeByName(new QName("priority"))
									.getValue()));
					this.tasks.add(t);
				}
				
				if (startElement.getName().getLocalPart() == (ICS_INFOS)) {
					// create the ics-info list
					this.icsInfos = new ArrayList<ICSInfo>();
					
				}

				if (startElement.getName().getLocalPart() == (ICS_INFO)) {
					ICSInfo ics = new ICSInfo();
					// id
					ics.setId(new Integer(startElement.getAttributeByName(
							new QName("id")).getValue()));
					// summary
					ics.setSummary(startElement.getAttributeByName(
							new QName("summary")).getValue());
					// description
					ics.setDescription(startElement.getAttributeByName(
							new QName("description")).getValue());
				    					
					// start time
					// TODO: Use constants instead of hard-coded strings
					DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					Date date = new Date();

					try {
						date = df.parse(startElement.getAttributeByName(
								new QName("startTime")).getValue());
						ics.setStartTime(date);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					// end time
					// TODO: Use constants instead of hard-coded strings
					df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					date = new Date();

					try {
						date = df.parse(startElement.getAttributeByName(
								new QName("endTime")).getValue());
						ics.setEndTime(date);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					// status
					ics.setStatus(this.fxtodoMain
							.getStatusByTitle(startElement.getAttributeByName(
									new QName("status")).getValue()));
					// priority
					ics.setPriority(this.fxtodoMain
							.getPriorityByTitle(startElement
									.getAttributeByName(new QName("priority"))
									.getValue()));
					
					// type
					ics.setICSInfoType(this.fxtodoMain.getICSInfoTypeByName(startElement
									.getAttributeByName(new QName("type"))
									.getValue()));
					// task-id
					ics.setTaskId(new Integer(startElement
							.getAttributeByName(
							new QName("taskId")).getValue()));
					
					// created
					// TODO: Use constants instead of hard-coded strings
					df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					date = new Date();

					try {
						date = df.parse(startElement.getAttributeByName(
								new QName("created")).getValue());
						ics.setCreated(date);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					icsInfos.add(ics);

				}
			}
		}
	}

	public List<Context> getContexts() {
		return contexts;
	}

	public List<Task> getTasks() {
		return tasks;
	}

	public List<ICSInfo> getIcsInfos() {
		return icsInfos;
	}
}
